using System;
using System.Collections.Generic;
using System.Linq;
using HappyBa.Core.Data;
using HappyBa.Core.Interfaces;

namespace HappyBa.Core.UserReport
{
    class UserStatisticsCalculator : IUserStatisticsCalculator
    {
        private readonly ITargetProccessFacade facade;
        private readonly Config config;
        private readonly IDataCache dataCache;

        public UserStatisticsCalculator(ITargetProccessFacade facade, Config config, IDataCache dataCache)
        {
            this.facade = facade;
            this.config = config;
            this.dataCache = dataCache;
        }

        public IEnumerable<DayUserReport> BuildReport(UserReportContext context)
        {
            var times = facade.GetTimes(config.Settings.Connection, context.Settings.DatesFrom??DateTime.Now, context.Settings.DatesTo ?? DateTime.Now, context.Users);
            if (context.Settings.RestrictTasksBySelectedInProfile)
            {
                var knownIds = dataCache.Metrics.EstimatableEntities.Select(x => x.Id);
                times = times.Where(x => knownIds.Contains(x.Assignable.Id)).ToArray();
            }
            var tasks = facade.GetAssignables(config.Settings.Connection, times.Select(x => x.Assignable.Id).Distinct()) ;
            foreach (var time in times)
            {
                time.Assignable = tasks.Single(x => x.Id == time.Assignable.Id);
            }
            foreach (var day in times.GroupBy(x=>x.Date.Date))
            {
                yield return new DayUserReport
                {
                    Date = day.Key,
                    Reports = new List<UserReport>(BuildUsers(day.ToArray()))
                };
            }
        }

        private static IEnumerable<UserReport> BuildUsers(IEnumerable<Time> times)
        {
            foreach (var user in times.GroupBy(x=>x.User.ToString()))
            {
                yield return new UserReport
                {
                    User = user.Key,
                    Tasks = new List<TaskReport>(BuildTasks(user.ToArray()))
                };
            }
        }

        private static IEnumerable<TaskReport> BuildTasks(IEnumerable<Time> times)
        {
            foreach (var time in times)
            {
                yield return new TaskReport
                {
                    Task = time.Assignable,
                    Time = time.Spent
                };
            }
        }
    }
}